﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using SuperSocket.Common;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Config;
using SuperSocket.SocketEngine;
using SuperSocket.SocketEngine.Configuration;
using SuperWebSocket;
using System.Collections;
using PhoneDBModel;

/// <summary>
/// Summary description for ChatWebSockets
/// </summary>
public class ChatWebSockets
{
    private Dictionary<string, WebSocketSession> m_Sessions = new Dictionary<string, WebSocketSession>();
    private object m_SessionSyncRoot = new object();
    private Dictionary<string, string> uidNameMap = new Dictionary<string, string>();
    private PhoneDBEntities dbe = new PhoneDBEntities();

    void StartSuperWebSocketByConfig()
    {
        var serverConfig = ConfigurationManager.GetSection("socketServer") as SocketServiceConfig;
        if (!SocketServerManager.Initialize(serverConfig))
            return;

        var socketServer = SocketServerManager.GetServerByName("SuperWebSocket") as WebSocketServer;

        HttpContext.Current.Application["WebSocketPort"] = socketServer.Config.Port;

        socketServer.CommandHandler += new CommandHandler<WebSocketSession, WebSocketCommandInfo>(socketServer_Receive);
        socketServer.NewSessionConnected += new SessionEventHandler<WebSocketSession>(socketServer_NewSessionConnected);
        socketServer.SessionClosed += new SessionClosedEventHandler<WebSocketSession>(socketServer_SessionClosed);

     

        if (!SocketServerManager.Start())
            SocketServerManager.Stop();
    }

    void socketServer_NewSessionConnected(WebSocketSession session)
    {
        lock (m_SessionSyncRoot)
        {
            m_Sessions.Remove(AESCypher.decryptString(session.Cookies["uid"]));
            m_Sessions.Add(AESCypher.decryptString(session.Cookies["uid"]), session);
            
            uidNameMap.Remove(AESCypher.decryptString(session.Cookies["uid"]));
            uidNameMap.Add(AESCypher.decryptString(session.Cookies["uid"]), AESCypher.decryptString(session.Cookies["name"])); 
        }

        //SendToAll("{\"Name\":\"System\", \"Message\": \"" + AESCypher.decryptString(session.Cookies["name"]) + " connected\"}");
    }

    void socketServer_SessionClosed(WebSocketSession session, CloseReason reason)
    {
        lock (m_SessionSyncRoot)
        {
            m_Sessions.Remove(AESCypher.decryptString(session.Cookies["uid"]));
            uidNameMap.Remove(AESCypher.decryptString(session.Cookies["uid"]));
        }

        if (reason == CloseReason.ServerShutdown)
            return;

        //SendToAll("{\"Name\":\"System\", \"Message\": \"" + session.Cookies["name"] + " disconnected\"}");
    }

    void socketServer_Receive(WebSocketSession session, WebSocketCommandInfo commandInfo)
    {
        if (commandInfo.Data.StartsWith("Message=") == true)
        {
            string data = commandInfo.Data.Replace("Message=", "");
            string to = data.Substring(0, data.IndexOf(":::"));
            to = uidNameMap.SingleOrDefault(x => x.Value == to).Key;
            if (to != null)
            {
                string msg = data.Substring(data.IndexOf(":::") + 3);

                ChatHistory ch = new ChatHistory();
                ch.Date = DateTime.Now;
                ch.Message = msg;
                ch.Received = false;
                ch.ReceiverId = int.Parse(to);
                ch.SenderId = int.Parse(AESCypher.decryptString(session.Cookies["uid"]));

                if (m_Sessions.Keys.Contains(AESCypher.decryptString(session.Cookies["uid"])))
                {
                    m_Sessions[to].SendResponseAsync("{\"Name\":\"" + AESCypher.decryptString(session.Cookies["name"]) + "\", \"Message\": \"" + msg + "\"}");
                    ch.Received = true;
                }


                dbe.ChatHistories.AddObject(ch);
                try
                {
                    dbe.SaveChanges();                    
                }
                catch
                {
                }
            }
        }
    }

    void SendToAll(string message)
    {
        lock (m_SessionSyncRoot)
        {
            foreach (var s in m_Sessions.Values)
            {
                //s.SendResponse(message);
                s.SendResponseAsync(message);
            }
        }
    }

    public void Application_Start()
    {
        LogUtil.Setup();
        StartSuperWebSocketByConfig();
    }

    public void Application_End()
    {
        SocketServerManager.Stop();
    }

	public ChatWebSockets()
	{
		//
		// TODO: Add constructor logic here
		//
	}
}